#include "debug.h"

#include "video.h"
#include "videoext.h"

#include "collision.h"
#include "object.h"
#include "draw.h"

#include <stdio.h>

#define LONG(hi,lo) (hi<<16)+lo
#define HI(val) (val<<16)
#define LO(val) val
#define LONGTOWORD LEFTRADIXLONG
#define LEFTRADIXLONG(val) ((val & 0xFFFF0000) >> 16) 
#define SWAPWORD(val) (((val&0x00FF)<<8)+((val&0xFF00)>>8))

long clock;
long timeFrame;
long delayTime;

extern byte v_16x16[];
extern byte vRam[];
extern byte fgRam[];
extern long *infopixels;

extern object* player;
extern object* objects;

extern long v_screenposx;
extern long v_screenposy;
extern word v_lookshift;
extern word v_anglebuffer;
extern word FFFFF76A;

extern byte v_jpadhold1;

char coordstr[25];
char coordstr2[25];
char coordstr3[25];
char coordstr4[25];
char coordstr5[25];
char tileinfo[50];
char tile16info[50];
char joypadinfo[50];
char statusinfo[50];
char renderinfo[50];
char sonicinfo1[50];
char sonicinfox[50];
char sonicinfoy[50];
char sonicinfo2[50];
char sonicinfo3[50];
char screeninfo[50];
char angleinfo[50];
char screeninfo2[50];
char tileinfo2[50];
char sensorinfo[50];
char varinfo[50];
char varinfo2[50];

char timeinfo[50];
char timeinfo2[50];
char objinfo[50];
char objinfo2[50];
char objinfo3[50];
char objinfo4[50];
char objinfo5[50];
char objinfo6[50];

char selitemtxt[50];

bool mousel, mouser;
int dbgmousex, dbgmousey;
int pfMouseX, pfMouseY;

int eightaddress;

struct menuItem
{
    int x;
    int y;
    int len;
    char text[50];
};

#define NUMITEMS 3
menuItem items[NUMITEMS] = { 
{ 2, 24, 25, "sonic variables" },
{ 2, 25, 25, "object info" },
{ 2, 26, 25, "tile info" }
};

int selitem=0;

object *oldSelect=(object*)0;
word oldGfx=0;

extern word *infotext;

//soniclib extended?
void SLX_S1DebugInfo()
{
     if (selitem == 1)
     {
         char *_joypadinfo=joypadinfo;
         for (signed int pn=-2; pn<2; pn++)
         {
	     byte n=*((&v_jpadhold1)+pn);
	     unsigned int i = 1 << (sizeof(n) * 8 - 1);
	     while (i > 0) 
	     {
		if (n & i) { *(_joypadinfo++)='1'; }
		else       { *(_joypadinfo++)='0'; }
		i >>= 1;
	     }
             (*_joypadinfo++)=' ';
          }
          char *_statusinfo=statusinfo;          byte n=objects[0].Status;
          unsigned int i = 1 << (sizeof(n) * 8 - 1);
          while (i > 0) 
          {
              if (n & i) { *(_statusinfo++)='1'; }
	      else       { *(_statusinfo++)='0'; }
	      i >>= 1;
          }
          (*_statusinfo++)=' ';
          char *_renderinfo=renderinfo;          n=objects[0].Render;
          i = 1 << (sizeof(n) * 8 - 1);
          while (i > 0) 
          {
              if (n & i) { *(_renderinfo++)='1'; }
	      else       { *(_renderinfo++)='0'; }
	      i >>= 1;
          }
          *(_renderinfo++)=' ';
     
         sprintf(sonicinfox, "X %x  %x  %i.%i", objects[0].X, objects[0].Xdec, objects[0].X, objects[0].ScreenY);
         sprintf(sonicinfoy, "Y %x  %x  %i.%i", objects[0].Y, objects[0].Ydec, objects[0].Y, objects[0].Yfract);
         sprintf(sonicinfo1, "Height %x  Width %x", objects[0].Height, objects[0].Width);
         sprintf(sonicinfo2, "VelX %x VelY %x Inertia %x  ", objects[0].VelocityX, objects[0].VelocityY, objects[0].Inertia);
         sprintf(sonicinfo3, "Angle %x  ", objects[0].Angle);
         sprintf(screeninfo, "Sonic Y distance from center %i", objects[0].Y - LEFTRADIXLONG(v_screenposy) - v_lookshift);
         sprintf(angleinfo, "v_anglebuffer: %d  FFFFF76A: %d", (signed char)v_anglebuffer, (signed char)FFFFF76A);
         sprintf(screeninfo2, "v_screenposx: %x v_screenposy %x", LEFTRADIXLONG(v_screenposx), LEFTRADIXLONG(v_screenposy));
         word *tileunderPtr=FindNearestTile(&objects[0], objects[0].Y+objects[0].Height, objects[0].X+objects[0].Width);
         word tileunder=SWAPWORD(*tileunderPtr);
         sprintf(tileinfo2, "tile under sonic: %x flipx %x flipy %x", (tileunder&0x7FF)*8, (tileunder&0x800)/0x800, (tileunder&0x1000)/0x1000);
         sprintf(varinfo, "invinc: %i spdsho: %i fntang: %i", getobjvariableword(0x30,objects[0]), getobjvariableword(0x32,objects[0]), objects[0].Variables[0x36-0x28]);
         sprintf(varinfo2, "jmping: %i ctllck: %i bckang: %i", objects[0].Variables[0x3C-0x28], getobjvariableword(0x3E,objects[0]), objects[0].Variables[0x37-0x28]);

         signed short sensorL, sensorR;
         signed short floorAngleL;
         signed short floorAngleR;
     
         FindFloor(&objects[0], objects[0].Y+objects[0].Height, objects[0].X-objects[0].Width, 0xD, 0, sensorL, 16, &floorAngleL);
         FindFloor(&objects[0], objects[0].Y+objects[0].Height, objects[0].X+objects[0].Width, 0xD, 0, sensorR, 16, &floorAngleR);
         sprintf(sensorinfo, "sensor L: %i sensor R: %i", sensorL, sensorR);
         
         DrawText_NoScrollExt(coordstr,25,1,1,infotext);
         DrawText_NoScrollExt(tileinfo,25,1,2,infotext);
         DrawText_NoScrollExt(tile16info,26,1,3,infotext);
         DrawText_NoScrollExt(joypadinfo,45,1,4,infotext);
         DrawText_NoScrollExt(statusinfo,8,1,5,infotext);
         DrawText_NoScrollExt(renderinfo,8,1,6,infotext);
         DrawText_NoScrollExt(sonicinfox,40,1,7,infotext);
         DrawText_NoScrollExt(sonicinfoy,40,1,8,infotext);
         DrawText_NoScrollExt(sonicinfo1,40,1,9,infotext);
         DrawText_NoScrollExt(sonicinfo2,40,1,10,infotext);
         DrawText_NoScrollExt(sonicinfo3,40,1,11,infotext);
         DrawText_NoScrollExt(screeninfo,40,1,12,infotext);
         DrawText_NoScrollExt(angleinfo,40,1,13,infotext);
         DrawText_NoScrollExt(screeninfo2,40,1,14,infotext);
         DrawText_NoScrollExt(tileinfo2,40,1,15,infotext);
         DrawText_NoScrollExt(sensorinfo,40,1,16,infotext);
         DrawText_NoScrollExt(varinfo,40,1,17,infotext);
         DrawText_NoScrollExt(varinfo2,40,1,18,infotext);
        
     }
     else if (selitem == 2)
     {
     
         object *mouseObj = SLX_FindObject(pfMouseX, pfMouseY);


      
         if (mouseObj != 0) 
         {
             char *_statusinfo=statusinfo;             byte n=objects[0].Status;
             unsigned int i = 1 << (sizeof(n) * 8 - 1);
             while (i > 0) 
             {
                 if (n & i) { *(_statusinfo++)='1'; }
	         else       { *(_statusinfo++)='0'; }
	         i >>= 1;
             }
             (*_statusinfo++)=' ';
             char *_renderinfo=renderinfo;             n=objects[0].Render;
             i = 1 << (sizeof(n) * 8 - 1);
             while (i > 0) 
             {
                 if (n & i) { *(_renderinfo++)='1'; }
	         else       { *(_renderinfo++)='0'; }
	         i >>= 1;
             }
             *(_renderinfo++)=' ';

             sprintf(objinfo, "at %i %i object %i", pfMouseX, pfMouseY, mouseObj-objects);
             sprintf(objinfo2, "ID %i", mouseObj->ID);
             sprintf(objinfo3, "Subtype %i", mouseObj->Subtype);
             sprintf(objinfo4, "X %i Y %i", mouseObj->X, mouseObj->Y);
             sprintf(objinfo5, "VelX %i VelY %i", mouseObj->VelocityX, mouseObj->VelocityY);
             
             
         }
         else
         {
             sprintf(objinfo, "select an object...");
         }
           
         DrawText_NoScrollExt(objinfo, 40,1,1,infotext);
         DrawText_NoScrollExt(objinfo2,40,1,2,infotext);
         DrawText_NoScrollExt(objinfo3,40,1,3,infotext);
         DrawText_NoScrollExt(objinfo4,40,1,4,infotext);
         DrawText_NoScrollExt(objinfo5,40,1,5,infotext);
         DrawText_NoScrollExt(objinfo6,40,1,6,infotext);
         DrawText_NoScrollExt(statusinfo,40,1,7,infotext);
         DrawText_NoScrollExt(renderinfo,40,1,8,infotext);
         DrawText_NoScrollExt("                     ",40,1,9,infotext);
         DrawText_NoScrollExt("                     ",40,1,10,infotext);
         DrawText_NoScrollExt("                     ",40,1,11,infotext);
         DrawText_NoScrollExt("                     ",40,1,12,infotext);
         DrawText_NoScrollExt("                     ",40,1,13,infotext);
         DrawText_NoScrollExt("                     ",40,1,14,infotext);
         DrawText_NoScrollExt("                     ",40,1,15,infotext);
         DrawText_NoScrollExt("                     ",40,1,16,infotext);
         DrawText_NoScrollExt("                     ",40,1,17,infotext);
         DrawText_NoScrollExt("                     ",40,1,18,infotext);
     }
     else if (selitem == 3)
     {
         int gameMouseX = dbgmousex/PIXELSIZE;
         int gameMouseY = dbgmousey/PIXELSIZE;

         int nearest8X = gameMouseX - (gameMouseX & 7);
         int nearest8Y = gameMouseY - (gameMouseY & 7);
         int selectScrollX = LEFTRADIXLONG(v_screenposx) & (7);
         int selectScrollY = LEFTRADIXLONG(v_screenposy) & (7);

         selectRegion(nearest8X-selectScrollX, nearest8Y-selectScrollY, 8, 8);
         
         DrawText_NoScrollExt(tileinfo, 40, 1, 1, infotext);
         DrawText_NoScrollExt(coordstr, 40 ,1, 2,infotext);
         DrawText_NoScrollExt(coordstr2 ,40, 1, 3,infotext);
         DrawText_NoScrollExt(coordstr3 ,40,1,4,infotext);
         DrawText_NoScrollExt(coordstr4 ,40,1,5,infotext);
         DrawText_NoScrollExt(coordstr5,40,1,6,infotext);
         DrawText_NoScrollExt(tile16info,40,1,7,infotext);
         DrawText_NoScrollExt("                     ",40,1,8,infotext);
         DrawText_NoScrollExt("                     ",40,1,9,infotext);
         DrawText_NoScrollExt("                     ",40,1,10,infotext);
         DrawText_NoScrollExt("                     ",40,1,11,infotext);
         DrawText_NoScrollExt("                     ",40,1,12,infotext);
         DrawText_NoScrollExt("                     ",40,1,13,infotext);
         DrawText_NoScrollExt("                     ",40,1,14,infotext);
         DrawText_NoScrollExt("                     ",40,1,15,infotext);
         DrawText_NoScrollExt("                     ",40,1,16,infotext);
         DrawText_NoScrollExt("                     ",40,1,17,infotext);
         DrawText_NoScrollExt("                     ",40,1,18,infotext);

         tileToPixelBuf(eightaddress, 8*10, 8*10, infopixels, INFOWIDTH,  INFOHEIGHT);
     }
     sprintf(timeinfo2, "dlt %i", delayTime);
     sprintf(timeinfo, "clk %i frm %i", clock, timeFrame);  
     DrawText_NoScrollExt(items[0].text, items[0].len, items[0].x, items[0].y, infotext);
     DrawText_NoScrollExt(items[1].text, items[1].len, items[1].x, items[1].y, infotext);
     DrawText_NoScrollExt(items[2].text, items[2].len, items[2].x, items[2].y, infotext);
     DrawText_NoScrollExt(timeinfo, 25, 2, 23, infotext);
     DrawText_NoScrollExt(timeinfo2, 25, 2, 22, infotext);
}

void SLX_UpdateMouse(int _mousex, int _mousey)
{
    dbgmousex = _mousex;
    dbgmousey = _mousey;

    pfMouseX = (dbgmousex/PIXELSIZE) + LEFTRADIXLONG(v_screenposx);     //playfield mouse x    (relative to v_screenposx)
    pfMouseY = (dbgmousey/PIXELSIZE) + LEFTRADIXLONG(v_screenposy);     //playfield mouse y    (relative to v_screenposy)

    int tilex = (dbgmousex/PIXELSIZE)/TILEW;
    int tiley = (dbgmousey/PIXELSIZE)/TILEH;
    int scrolledX = LEFTRADIXLONG(getHScroll(tiley*8));
    int scrolledY = LEFTRADIXLONG(getVScroll());
    
    int tileScrolledX = (scrolledX/8)%64;
    int tileScrolledY = (scrolledY/8)%64;
    
    int tileOffsetX = (tilex - tileScrolledX) % 64;
    int tileOffsetY = (tiley - tileScrolledY) % 64;

    sprintf(coordstr, "MOUSEX %i MOUSEY %i", dbgmousex, dbgmousey);
    sprintf(coordstr2, "PMOUSX %i PMOUSY %i", pfMouseX, pfMouseY);
    sprintf(coordstr3, "tilex %i tiley %i", tilex, tiley);
    sprintf(coordstr4, "scrolled %i %i", scrolledX, scrolledY);
    sprintf(coordstr5, "tilewise %i %i", tileScrolledX, tileScrolledY); 
    

    word *sixteen=DrawBlocks(&v_screenposx,dbgmousey/PIXELSIZE,dbgmousex/PIXELSIZE,0);
    long sixteenaddress=(long)sixteen;
    
    int eightin16=(tilex%2)+((tiley%2)*2);
    eightaddress=SWAPWORD(sixteen[eightin16]);
    //word flipx=(fgRamVal&0x800)>>11;
    //word flipy=(fgRamVal&0x1000)>>12;
    //word line=(fgRamVal&0x6000)>>13;
    //word priority=(fgRamVal&0x8000)>>15;
    word tileindex=(eightaddress&0x7FF);    


    sprintf(tileinfo, "CURRENT 8 BY 8 %i", tileindex);
    
    //sprintf(tile16info, "CURRENT 16 BY 16 %04X", (sixteenaddress-(int)currentZone.v_16x16));
    sprintf(tile16info, "CURRENT 16 %04X", (sixteenaddress-(int)&v_16x16));

    //

    SLX_CheckSelectText();

    
}

void SLX_UpdateMouseClick(bool left, bool right)
{
    mousel = left;
    mouser = right;

    SLX_CheckSelectText();
}


void SLX_CheckSelectText()
{
    //grab mouse position relative to extended window
    int mousexExt = dbgmousex - DISPLAYWIDTH;
    int mouseyExt = dbgmousey;
 
    
    bool itemSelected = false;
    if (mousel)
    {
        for (int lp=0; lp<NUMITEMS; lp++)
        {
            int itemL = (items[lp].x * 8 * PIXELSIZE);
            int itemR = itemL + (items[lp].len*8*PIXELSIZE);
            if ((mousexExt >= itemL) && (mousexExt <= itemR))
            {
                int itemT = items[lp].y * 8*PIXELSIZE;
                int itemB = itemT + (8*PIXELSIZE);
                if ((mouseyExt >= itemT) && (mouseyExt <= itemB))
                {
                    selitem = lp+1;
                    itemSelected = true;
                }
            }
            
        }
        if (!itemSelected) { selitem = 0; }
    }
    
    
}


object *SLX_FindObject(int x, int y)
{
    object *curObj;
    for (int count = 0; count <= 0x7F; count++)
    {
        curObj = &objects[count];

        int width, height;
        if ( ((width = curObj->Width) == 0) || ((height = curObj->Height) == 0) )
            width = curObj->ActionWidth; height = width;

        int objL = curObj->X - width;
        int objR = curObj->X + width;
        int objT = curObj->Y - height;
        int objB = curObj->Y + height;

        if ((x > objL) && (x < objR) && (y > objT) && (y < objB))
            return curObj;
    }

    return 0;
}


